import { join } from 'node:path'
import fs from 'node:fs'
import { Readability, type ReadabilityResult } from '../src/index.js'
import { load } from 'cheerio'
import { prettyPrint } from './utils.js'
import { fileURLToPath } from 'node:url'

const debug = false
const testPageRoot = fileURLToPath(new URL('./test-pages', import.meta.url))
const FFX_UA =
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:80.0) Gecko/20100101 Firefox/80.0'
const argURL = process.argv[3] as string | undefined

function generateTestcase(slug: string) {
    const destRoot = join(testPageRoot, slug)

    const dirExists = fs.existsSync(destRoot)
    if (!dirExists) fs.mkdirSync(destRoot)

    const sourcePath = join(destRoot, 'source.html')
    const srcExists = fs.existsSync(sourcePath)

    if (srcExists) {
        const data = fs.readFileSync(sourcePath, { encoding: 'utf-8' })
        onResponseReceived(data, destRoot)
    } else {
        fetchSource(argURL).then((text) => {
            fs.writeFileSync(sourcePath, text)
            onResponseReceived(text, destRoot)
        })
    }
}

async function fetchSource(url: string | undefined) {
    if (!url) {
        console.error("You should pass a URL if the source doesn't exist yet!")
        process.exit(1)
    }

    const headers = { 'User-Agent': FFX_UA }

    const response = await fetch(url, { headers })

    if (debug) {
        console.log('STATUS:', response.status)
        console.log('HEADERS:', JSON.stringify(response.headers))
    }
    return await response.text()
}

function onResponseReceived(text: string, destRoot: string) {
    if (debug) {
        console.log('writing')
    }

    if (debug) {
        console.log('Running readability stuff')
    }

    runReadability(
        text,
        join(destRoot, 'expected.html'),
        join(destRoot, 'expected-metadata.json'),
    )
}

function runReadability(
    source: string,
    destPath: string,
    metadataDestPath: string,
) {
    const uri = 'http://fakehost/test/page.html'
    const $ = load(source, { baseURI: uri })

    // We pass `caption` as a class to check that passing in extra classes works,
    // given that it appears in some of the test documents.
    const reader = new Readability($, { classesToPreserve: ['caption'] })
    const result = reader.parse() as Partial<ReadabilityResult>
    const content = prettyPrint(result.content || null)

    if (!content) {
        console.error(
            'No content generated by readability, not going to write expected.html!',
        )
        return
    }

    fs.writeFileSync(destPath, content)

    // Delete the result data we don't care about checking.
    delete result.content
    delete result.textContent
    delete result.length

    fs.writeFileSync(metadataDestPath, JSON.stringify(result, null, 2) + '\n')
}

if (process.argv.length < 3) {
    console.error(
        "Need at least a destination slug and potentially a URL (if the slug doesn't have source).",
    )
    process.exit(0)
}

if (process.argv[2] === 'all') {
    const files = fs.readdirSync(testPageRoot)

    files.forEach(function (file) {
        generateTestcase(file)
    })
} else {
    generateTestcase(process.argv[2] as string)
}
